﻿using PGMHelper;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms.DataVisualization.Charting;

namespace HystereticBasic
{
    /// <summary>
    /// 方法
    /// </summary>
    public static class HystereticHelper
    {
        /// <summary>
        /// 获得所有txt文件路径
        /// </summary>
        /// <param name="directPath"></param>
        /// <returns></returns>
        public static List<string> GetFileList(string directPath)
        {
            //初始化
            var pathList = new List<string>();
            //文件夹不存在则返回
            if (!Directory.Exists(directPath))
            {
                MessageBoxExtern.Warnning(string.Format("文件夹不存在！路径：{0}", directPath));
                return pathList;
            }
            //获得所有TXT文件路径
            pathList = WilsonHelper.GetSpecificFiles(directPath, ".txt");
            //文件路径为空直接返回
            if (pathList.Count == 0)
            {
                MessageBoxExtern.Warnning(string.Format("txt文件不存在！路径：{0}", directPath));
            }
            return pathList;
        }

        /// <summary>
        /// 获得相交点
        /// </summary>
        /// <param name="line1"></param>
        /// <param name="line2"></param>
        /// <param name="interPt"></param>
        /// <returns></returns>
        private static bool GetIntersection(MontForceDispObj line1, MontForceDispObj line2, out ForceDispBasicPair interPt)
        {
            //容差
            var tol = GlobalParam.DispTol;
            //初始化
            interPt = new ForceDispBasicPair();
            //数据存在
            if (line1.Count < 2 || line2.Count < 2) return false;
            //获得点
            var L1i = line1.First(); var L1j = line1.Last();
            var L2i = line2.First(); var L2j = line2.Last();
            //计算斜率
            var slopeI = L1i.GetStiffness(L1j);
            var slopeJ = L2i.GetStiffness(L2j);
            //函数指针
            Func<ForceDispBasicPair, ForceDispBasicPair, bool> isVetX = (p1, p2) =>
            {
                return Math.Abs(p1.Disp - p2.Disp) < tol;
            };
            //如果Line1与y轴垂直
            if (isVetX(L1i, L1j))
            {
                //如果Lin2也与Y轴垂直
                if (isVetX(L2i, L2j)) return false;
                //存在交点
                var force = slopeJ * (L1i.Disp - L2i.Disp) + L2i.Force;
                //构造点
                interPt = new ForceDispBasicPair(L1i.Disp, force);
                return true;
            }
            //如果Line2与Y轴垂直
            else if (isVetX(L2i, L2j))
            {
                //如果Lin1也与Y轴垂直
                if (isVetX(L1i, L1j)) return false;
                //存在交点
                var force = slopeI * (L2i.Disp - L1i.Disp) + L1i.Force;
                //构造点
                interPt = new ForceDispBasicPair(L2i.Disp, force);
                return true;
            }
            //两直线平行
            else if (Math.Abs(slopeI - slopeJ) < tol) return false;
            //不平行
            else
            {
                //计算相交点
                var disp = (slopeI * L1i.Disp - L1i.Force + L2i.Force - slopeJ * L2i.Disp) / (slopeI - slopeJ);
                var force = slopeI * (disp - L1i.Disp) + L1i.Force;
                //构造点
                interPt = new ForceDispBasicPair(disp, force);
                return true;
            }
        }

        /// <summary>
        /// 获得相交点
        /// </summary>
        /// <param name="line1"></param>
        /// <param name="line2"></param>
        /// <param name="interPt"></param>
        /// <returns></returns>
        public static bool GetIntersectionInLine(MontForceDispObj line1, MontForceDispObj line2, out ForceDispBasicPair interPt)
        {
            //容差
            var tol = GlobalParam.DispTol;
            //初始化
            interPt = new ForceDispBasicPair();
            //相交点范围
            var dispMin = Math.Max(line1.DispMinPoint.Disp, line2.DispMinPoint.Disp);
            var dispMax = Math.Min(line1.DispMaxPoint.Disp, line2.DispMaxPoint.Disp);
            //范围不存在
            if (dispMin - tol > dispMax) return false;
            //判断是否相交
            if (!GetIntersection(line1, line2, out interPt)) return false;
            //相交点是否在线内
            return ((interPt.Disp >= dispMin - tol) && (interPt.Disp <= dispMax + tol)); ;
        }

        /// <summary>
        /// 设定绘图区外观
        /// </summary>
        /// <param name="chart"></param>
        public static void SetChartApperance(Chart chart)
        {
            //Chart
            chart.SetApperance(StringAlignment.Center, false, isLegendAvailabel: false);
            //清空序列数据
            chart.Series.Clear();
            //科学技术法
            chart.SetAxisFormat(ChartAxisType.AxisY, AxisFormat.Science, 1);
            chart.SetAxisFormat(ChartAxisType.AxisX, AxisFormat.Science, 1);
            //添加标题
            chart.AddTitles("力位移曲线", "位移", "力");
        }

        /// <summary>
        /// 获得精度
        /// </summary>
        /// <param name="dataType"></param>
        /// <returns></returns>
        public static int GetDemical(DataType dataType)
        {
            switch (dataType)
            {
                //位移
                case DataType.CyclicDisps:
                case DataType.CycleMaxDisp:
                case DataType.AbsCycleMaxDisp:
                case DataType.SkeletonDisps:
                case DataType.PositiveLoadingDisp:
                case DataType.NegativeLoadingDisp:
                case DataType.AbsUnloadDisp:
                case DataType.UnloadDisp:
                case DataType.SmoothCyclicDisps:
                case DataType.NumericalCyclicDisps:
                case DataType.NumericalSkeletonDisps:
                    return 5;

                //力
                case DataType.CyclicForces:
                case DataType.SkeletonForces:
                case DataType.CycleMaxForce:
                case DataType.AbsCycleMaxForce:
                case DataType.SmoothCyclicForces:
                case DataType.NumericalCyclicForces:
                case DataType.NumercalSkeletonForces:
                    return 1;

                //系数
                case DataType.SecantStiffnessRatio:
                case DataType.ViscousDampingRatio:
                case DataType.UnloadDispRatio:
                case DataType.CycleMaxForceRatio:
                    return 3;

                //整形
                case DataType.CycleIndex:
                case DataType.SkeletonOrder:
                case DataType.SmoothCyclicOrders:
                    return 0;

                //延性相关
                case DataType.DuctilityYieldForce:
                case DataType.DuctilityPeakForce:
                case DataType.DuctilityUltimateForce:
                    return 1;

                //未知
                default: return 2;
            }
        }

        /// <summary>
        /// 获得数据点描述
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public static string GetDescp(DataType dataType)
        {
            switch (dataType)
            {
                case DataType.CyclicDisps: return "滞回曲线Disp";
                case DataType.CyclicForces: return "滞回曲线Force";
                case DataType.SkeletonDisps: return "骨架曲线Disp";
                case DataType.SkeletonForces: return "骨架曲线Force";

                case DataType.SkeletonOrder: return "骨架数据点编号";

                case DataType.SmoothCyclicDisps: return "平滑曲线Disp";
                case DataType.SmoothCyclicForces: return "平滑曲线Force";
                case DataType.SmoothCyclicOrders: return "平滑曲线数据点编号";

                case DataType.NumericalCyclicDisps: return "数值滞回曲线Disp";
                case DataType.NumericalSkeletonDisps: return "数值骨架曲线Disp";

                case DataType.NumericalCyclicForces: return "数值滞回曲线Force";
                case DataType.NumercalSkeletonForces: return "数值骨架曲线Force";

                case DataType.CycleMaxDisp:
                case DataType.AbsCycleMaxDisp:
                    return "滞回环最大位移Disp";

                case DataType.PositiveLoadingDisp: return "正向加载历史Disp";
                case DataType.NegativeLoadingDisp: return "负向加载历史Disp";

                case DataType.AccumulateEnergy: return "累积耗能面积";
                case DataType.ViscousDampingRatio: return "等效粘滞系数";
                case DataType.SecantStiffness: return "割线刚度";
                case DataType.SecantStiffnessRatio: return "刚度退化系数";

                case DataType.CycleIndex: return "滞回环序号";

                case DataType.AbsUnloadDisp:
                case DataType.UnloadDisp:
                    return "滞回环残余变形Disp";

                case DataType.UnloadDispRatio: return "残余变形占比";

                case DataType.CycleMaxForce:
                case DataType.AbsCycleMaxForce:
                    return "滞回环峰值力Force";

                case DataType.CycleMaxForceRatio:
                    return "滞回环峰值力系数";

                case DataType.DuctilityYieldForce:
                    return "等效屈服点力";
                case DataType.DuctilityYieldDisp:
                    return "等效屈服点位移";

                case DataType.DuctilityPeakForce:
                    return "峰值点力";
                case DataType.DuctilityPeakDisp:
                    return "峰值点位移";


                case DataType.DuctilityUltimateForce:
                    return "极限点力";
                case DataType.DuctilityUltimateDisp:
                    return "极限点位移";
                case DataType.DuctilityFactor:
                    return "延性系数";

                default: return dataType.ToString();
            }
        }

        /// <summary>
        /// 获得数据点描述
        /// </summary>
        /// <param name="dataType"></param>
        /// <param name="method"></param>
        /// <returns></returns>
        public static string GetDescp(DataType dataType,
            DuctilityMethod method)
        {
            switch (method)
            {
                case DuctilityMethod.Energy:
                    return "能量等效法-" + GetDescp(dataType);
                case DuctilityMethod.Park:
                    return "Park法-" + GetDescp(dataType);
                case DuctilityMethod.General:
                    return "通用屈服法-" + GetDescp(dataType);
                case DuctilityMethod.AVG:
                    return "平均值-" + GetDescp(dataType);
                default:
                    return string.Empty;
            }
        }
    }
}
